local log = require "modules.commhm.log"
local mis_config = require "mis_config"
local t_retCode = mis_config.t_retCode
local mis_data = require "mis_data"
local mis_bridge = require "mis_bridge"
local uu = require "modules.commhm.utils"
local mis_tools = require "mis_tools"
local mis_log = require "mis_log"
local mis_common = require "mis_common"

local LOG_NAME = "mis_currency"

local NATIONAL_SHARE = {
    cache_name = "national_share",
    key = "national_rank",
    expire_time = 60 * 5,
}

local M = {}


--=========================== 2022国庆活动 start=============================
--前置检测
local function pre_national_conf()
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local ver = ngx.ctx.m_params.ver
    local t_national_conf = mis_data.t_currency.t_national_conf

    local _check, _info = mis_tools.check_limit(t_national_conf, apiid, ver)
    if not _check then 
        return t_retCode.n_AUTH_ERR, _info
    end

    return t_retCode.n_OK
end

M.reset_national_data = function (id)
    local ok, data = mis_data.get_user():get_national_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    local ok2, code = mis_data.get_user():set_national_data(nil)
    return t_retCode.n_OK
end

local function combine_profile_cloud()
    local rank = {}
    local map_id = mis_config.t_rank_server.s_mapid
    local t_name = mis_config.t_rank_server.s_name

    local i_ret, i_result = mis_bridge.get_cloud_national_rank(map_id, t_name)
    if not i_ret or not i_result then 
        log.day_list(LOG_NAME, "[ERROR] national_get_rank", "get_cloud_national_rank error!")
        return {}
    end

    local op_uin_list = {}
    for _, v in ipairs(i_result) do
        table.insert(op_uin_list, v.uin)
    end
    local op_uin_list_str =  table.concat(op_uin_list, '-')

    local uin = tonumber(ngx.ctx.m_params.uin) or 1000
    local n_code, s_desc = mis_bridge.query_profile_info(uin, op_uin_list_str)
    if n_code~=t_retCode.n_OK or not s_desc then 
        log.day_list(LOG_NAME, "[ERROR] national_get_rank", "query_profile_info error!", "uin="..uin
            , "s_desc="..uu.to_str(s_desc), "op_uin_list_str="..uu.to_str(op_uin_list_str))
        return {}
    end

    for k, v in ipairs(op_uin_list) do
        local user = {}
        user.uin = v
        user.score = '*更新中*'
        if (i_result[k] and  i_result[k].value) then 
            user.score = i_result[k].value
        end
        if s_desc[k] and s_desc[k].profile then 
            user.head_frame_id = s_desc[k].profile.head_frame_id
            if s_desc[k].profile.RoleInfo and s_desc[k].profile.RoleInfo.head_id then 
                user.name = s_desc[k].profile.RoleInfo.NickName
                user.head_id = s_desc[k].profile.RoleInfo.head_id
            end
        end 
        if not user.name then 
            user.name = '*已删除*'
        end
        if not user.head_id then 
            user.name = 2
        end

        table.insert(rank, user)
    end

    return rank
end  

local function get_user_rankinfo(uin)
    if not uin then 
        return {}
    end

    local map_id = mis_config.t_rank_server.s_mapid
    local t_name = mis_config.t_rank_server.s_name
    local i_ret, i_result = mis_bridge.get_cloud_national_user_rank(map_id, t_name, uin)
    if not i_ret or not i_result then 
        --log.day_list(LOG_NAME, "[ERROR] get_user_rankinfo", "get_cloud_national_user_rank error!", "uin="..uin)
        --return {}
    end

    local op_uin_list = {uin}
    local op_uin_list_str =  table.concat(op_uin_list, '-')

    local n_code, s_desc = mis_bridge.query_profile_info(uin, op_uin_list_str)
    if n_code~=t_retCode.n_OK or not s_desc then 
        log.day_list(LOG_NAME, "[ERROR] get_user_rankinfo", "query_profile_info error!", "uin="..uin
            , "s_desc="..uu.to_str(s_desc), "op_uin_list_str="..uu.to_str(op_uin_list_str))
        return {}
    end

    local user_info = {}
    for k, v in ipairs(op_uin_list) do
        user_info.uin = v
        user_info.score = 0
        user_info.rank_result = 0
        if (i_result and i_result.rankIndex) then 
            user_info.rank_result = i_result.rankIndex
        end
        if (i_result and i_result.rankValue) then 
            user_info.score = i_result.rankValue
        end
        if s_desc[k] and s_desc[k].profile then 
            user_info.head_frame_id = s_desc[k].profile.head_frame_id
            if s_desc[k].profile.RoleInfo and s_desc[k].profile.RoleInfo.head_id then 
                user_info.name = s_desc[k].profile.RoleInfo.NickName
                user_info.head_id = s_desc[k].profile.RoleInfo.head_id
            end
        end 
        if not user_info.name then 
            user_info.name = '*已删除*'
        end
        if not user_info.head_id then 
            user_info.name = 2
        end
    end

    return user_info
end  

local function get_share_rank()
    local iret, rank = mis_tools.get_nginx_share(NATIONAL_SHARE.cache_name, NATIONAL_SHARE.key)
    if not iret then
        return {}, "get_rank_nginx_share_error!"
    end

    if not rank then
        rank = combine_profile_cloud()
        if #rank>0 then 
            local expire_time = mis_config.t_rank_server.s_exptime
            mis_tools.set_nginx_share(NATIONAL_SHARE.cache_name, NATIONAL_SHARE.key, rank, expire_time)
        end 
    end

    return rank or {}
end

--国庆首页
--参数： 无
--返回值： 
    --total_score 星之乐代币总数
    --配置上的地图奖励状态  0未打卡 1已打卡(可领代币) 2已打卡(已领代币)
M.national_home_page = function ()
    local t_pre_check, t_pre_error = pre_national_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end
    
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local t_national_conf = mis_data.t_currency.t_national_conf
    --log.debug("t_national_conf="..uu.to_str(t_national_conf))

    if (not uin) or (not apiid) or (not t_national_conf) 
    or (not t_national_conf.task_cfg) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end

    local ok, national_data = mis_data.get_user():get_national_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if not national_data then 
        national_data = {}
        national_data.task_data = {}
    end
    if not national_data.task_data then 
        national_data.task_data = {}
    end

    --
    mis_tools.update_task_info(uin, t_national_conf.task_cfg, national_data.task_data)

    local n_code, _desc = mis_data.get_user():set_national_data(national_data)
    if n_code ~= t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] moon_task_status", "set_national_data error!", "uin="..uin)
        return n_code, _desc
    end

    --主页上还要显示排行榜数据
    --[[
    national_data.task_data.rank_result = 0
    local rank = get_share_rank()
    for k, v in pairs(rank or {}) do
        if tonumber(v.uin)==uin then
            national_data.task_data.rank_result = k
        end
    end
    --]]

    return  t_retCode.n_OK, national_data.task_data
end

--国庆活动上报完成某个任务
--参数: 
    --times：完成次数 [每日登录X分钟，就需要上报X，如5分钟就传5；]
    --event:事件类型：该任务配置表上的event类型
    --special_key 1005打卡地图需要上报
--返回值：0 or 错误码
M.national_finsh_task = function ()
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local t_pre_check, t_pre_error = pre_national_conf()
    if t_pre_check~=t_retCode.n_OK then 
        log.day_list(LOG_NAME, "[ERROR] national_finsh_task", "pre_national_conf error!", "uin="..uin)
        return t_pre_check, t_pre_error
    end

    local apiid = tonumber(ngx.ctx.m_params.apiid)
    
    local event = tonumber(ngx.ctx.m_params.event)
    local times = tonumber(ngx.ctx.m_params.times) 
    local special_key = tonumber(ngx.ctx.m_params.special_key)
    local t_national_conf = mis_data.t_currency.t_national_conf

    if (not apiid) or (not event) or (not times) or (not uin) 
    or (not t_national_conf) 
    or (not t_national_conf.task_cfg) then 
        log.day_list(LOG_NAME, "[ERROR] national_finsh_task", "param error!", "uin="..uin)
		return t_retCode.n_PARAM_ERR, 'param error'
	end

    local ok, national_data = mis_data.get_user():get_national_data()
    if ok~=t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] national_finsh_task", "get_national_data error!", "uin="..uin)
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if not national_data then 
        national_data = {}
        national_data.task_data = {}
    end
    if not national_data.task_data then 
        national_data.task_data = {}
    end
    local ok2, rewards = mis_tools.update_task(event, times, national_data.task_data, t_national_conf.task_cfg, special_key)
    if not ok2 then 
        log.day_list(LOG_NAME, "[ERROR] national_finsh_task", "no finish task!", "uin="..uin, "event="..event
            , "times="..times, "special_key="..(special_key or "nil"))
        return t_retCode.n_WORK_ERR, 'update_task error--->no finish task!'
    end

    --只埋点打卡任务
    if event==1005 then 
        --当是打卡任务时，把其次数记录下来
        if not national_data.task_data.finish_count_1005 then 
            national_data.task_data.finish_count_1005 = 1
        else
            national_data.task_data.finish_count_1005 = national_data.task_data.finish_count_1005 + 1
        end 
        --埋点数据
        mis_log.remote_pure_day("dreamcity_number", mis_common.table_to_json({
            ip = ngx.ctx.m_params.s_remoteAddr or ngx.ctx.xff or ngx.var.remote_addr or "nil",
            uin = uin,
            time = ngx.ctx.m_params.createTime or uu.now(),
            country = ngx.ctx.m_params.country or 'nil',
            apiid = ngx.ctx.m_params.apiid or 'nil',
            ver = ngx.ctx.m_params.ver or 'nil',
            lang = ngx.ctx.m_params.lang or 'nil',

            key = 'finish',
            type = "dreamcity_number",
            number = national_data.task_data.finish_count_1005 or 0,
        }))

        local n_code, n_desc = mis_data.get_user():set_national_data(national_data)
        if n_code ~= t_retCode.n_OK then
            log.day_list(LOG_NAME, "[ERROR] national_finsh_task", "set_national_data error!", "uin="..uin)
            return n_code, n_desc
        end
    end

    --log.day_list(LOG_NAME, '[INFO] national_finsh_task', "apiid="..apiid, 'uin='..uin, "ver="..(ngx.ctx.m_params.ver or 'nil')
    --    , 'times='..times, 'event='..event, "special_key="..(special_key or "nil")
    --    , 'rewards='..uu.to_str(rewards), '[not add now!]now total_score='..(national_data.task_data.total_score or "nil")
    --    , 'event_times_data='..(national_data.task_data.events_finish_times[event] or "nil"))

    return t_retCode.n_OK, rewards
end

--领取任务积分
--参数： task_id 领取奖励的任务ID
--返回值：
    --num 数量
    --itemId 物品ID
M.national_get_task_rewards = function ()
    local t_pre_check, t_pre_error = pre_national_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local task_id = tonumber(ngx.ctx.m_params.task_id)
    if (not uin) or (not apiid) or (not task_id) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end

    local ok, national_data = mis_data.get_user():get_national_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if (not national_data) 
    or (not national_data.task_data) 
    or (not national_data.task_data.total_score)
    or (not national_data.task_data.task_list) 
    or (not national_data.task_data.task_list[task_id]) 
    or (not national_data.task_data.task_list[task_id].bonus)
    or (not national_data.task_data.task_list[task_id].bonus.num) 
    or (not tonumber(national_data.task_data.task_list[task_id].bonus.num)) then 
        return t_retCode.n_WORK_ERR, '[ERROR] national_get_task_rewards no national_data!'
    end

    if national_data.task_data.task_list[task_id].status ~= mis_tools.REWARDS_STATUS.READY then 
        return t_retCode.n_WORK_ERR, '[ERROR] national_get_task_rewards not ready!'
    end

    local task_data = national_data.task_data
    task_data.task_list[task_id].status = mis_tools.REWARDS_STATUS.ALREADY
    national_data.task_data.total_score = national_data.task_data.total_score + tonumber(national_data.task_data.task_list[task_id].bonus.num)  

    local n_code, _desc = mis_data.get_user():set_national_data(national_data)
    if n_code ~= t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] national_get_task_rewards", "set_national_data error!", "uin="..uin)
        return n_code, _desc
    end

    log.day_list(LOG_NAME, '[INFO] national_get_task_rewards ok', 'uin='..uin, "apiids="..apiid
        , "add_score="..tonumber(national_data.task_data.task_list[task_id].bonus.num)
        , "task_data.score="..national_data.task_data.total_score
        , "now_time="..uu.now()
    )

    return  t_retCode.n_OK, task_data.task_list[task_id].bonus
end

--兑换商店
--参数： 无
--返回值： status 0正常可兑换 1已拥有 2兑换次数不足 
M.national_exchange_shop = function ()
    local t_pre_check, t_pre_error = pre_national_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local t_national_conf = mis_data.t_currency.t_national_conf

    if (not uin) or (not apiid) or (not t_national_conf)  
    or (not t_national_conf.shop_cfg) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end

    local ok, national_data = mis_data.get_user():get_national_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if (not national_data) 
    or (not national_data.task_data) 
    or (not national_data.task_data.total_score) then  
        return t_retCode.n_WORK_ERR, '[ERROR] national_get_task_rewards no national_data!'
    end

    local new_data_flag = false
    if (not national_data.shop_data) then
        national_data.shop_data = {}
        new_data_flag = true
    end

    local shop_info, update_flag = mis_tools.exchange_shop(t_national_conf.shop_cfg, national_data.shop_data)
 
    if new_data_flag or update_flag then 
        local n_code, _desc = mis_data.get_user():set_national_data(national_data)
        if n_code ~= t_retCode.n_OK then
            log.day_list(LOG_NAME, "[ERROR] national_exchange_shop", "set_national_data error!", "uin="..uin)
            return n_code, _desc
        end
    end

    local ret_msg = {}
    ret_msg.shop_info = shop_info
    ret_msg.total_score = national_data.task_data.total_score

    return  t_retCode.n_OK, ret_msg
end

--兑换商店兑换物品
--参数：item_id 商店配置索引ID
--返回值： 兑换到的物品+当前总分
M.national_exchange_items = function ()
    local t_pre_check, t_pre_error = pre_national_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local item_id =  tonumber(ngx.ctx.m_params.item_id)
    local t_national_conf = mis_data.t_currency.t_national_conf

    if (not uin) or (not apiid) or (not item_id) 
    or (not t_national_conf)
    or (not t_national_conf.shop_cfg)
    or (not t_national_conf.shop_cfg[item_id]) 
    or (not t_national_conf.shop_cfg[item_id].propId)
    or (not t_national_conf.shop_cfg[item_id].propNum)
    or (not t_national_conf.shop_cfg[item_id].cost) 
    or (not t_national_conf.shop_cfg[item_id].exCount) 
    or (not tonumber(t_national_conf.shop_cfg[item_id].propId)) 
    or (not tonumber(t_national_conf.shop_cfg[item_id].propNum))
    or (not tonumber(t_national_conf.shop_cfg[item_id].cost))
    or (not tonumber(t_national_conf.shop_cfg[item_id].exCount)) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end

    local ok, national_data = mis_data.get_user():get_national_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end 
    if (not national_data) 
    or (not national_data.shop_data) 
    or (not national_data.task_data)
    or (not national_data.task_data.total_score) then
        return t_retCode.n_WORK_ERR, '[ERROR] national_exchange_items no national_data!'
    end

    local cost_money = (tonumber(t_national_conf.shop_cfg[item_id].cost))
    --代币是否充足
    if (national_data.task_data.total_score) < cost_money then
        return t_retCode.n_WORK_ERR, '[ERROR] national_exchange_items money not enough!' 
    end 

    local propId = tonumber(t_national_conf.shop_cfg[item_id].propId)
    if not propId then 
        return t_retCode.n_PARAM_ERR, 'param error'   
    end
    --兑换次数是否充足
    if (national_data.shop_data[propId]) 
    and (tonumber(national_data.shop_data[propId]))
    and (tonumber(national_data.shop_data[propId]) >= tonumber(t_national_conf.shop_cfg[item_id].exCount) ) then 
        return t_retCode.n_WORK_ERR, '[ERROR] national_exchange_items exCount not enough!'
    end

    local reward = t_national_conf.shop_cfg[item_id]
    --发给账号服需要这种结构
    local send_rewards = {}
    local one_reward = {}
    one_reward.id  = tonumber(reward.propId)
    one_reward.num  = tonumber(reward.propNum)
    table.insert(send_rewards, one_reward)

    --扣代币
    local op_total_score = national_data.task_data.total_score
    national_data.task_data.total_score = national_data.task_data.total_score - cost_money
    --次数累计
    if not national_data.shop_data[propId] then
        national_data.shop_data[propId] = 1
    else
        national_data.shop_data[propId] = national_data.shop_data[propId] + 1
    end

    --账号服发奖
    if #send_rewards>0 then
        --账号服发奖
        local ok2, reason_1, s_items, s_reason = mis_bridge.add_items(uin, send_rewards, "mis_currency", mis_config.t_workType.s_NATIONAL)
        if ok2~=t_retCode.n_OK then 
            log.day_list(LOG_NAME, '[ERROR] national_exchange_items call accout error!', "uin="..uin, "apiid="..apiid, "send_rewards="..uu.to_str(send_rewards)
                ,"accout_ret="..uu.to_str(ok2), "reason_1="..reason_1, "s_items="..uu.to_str(s_items), "s_reason="..s_reason)
            return t_retCode.n_SYS_ERR, "call account add_items error!"
        end
    end
    
    --set
    local n_code, _desc = mis_data.get_user():set_national_data(national_data)
    if n_code ~= t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] national_exchange_items", "set_national_data error!", "uin="..uin)
        return n_code, _desc
    end

    local ret_msg = {}
    ret_msg.total_score = national_data.task_data.total_score
    ret_msg.send_rewards = send_rewards

    --埋点数据
    mis_log.remote_pure_day("dreamcity_receive", mis_common.table_to_json({
        ip = ngx.ctx.m_params.s_remoteAddr or ngx.ctx.xff or ngx.var.remote_addr or "nil",
        uin = uin,
        time = ngx.ctx.m_params.createTime or uu.now(),
        country = ngx.ctx.m_params.country or 'nil',
        apiid = ngx.ctx.m_params.apiid or 'nil',
        ver = ngx.ctx.m_params.ver or 'nil',
        lang = ngx.ctx.m_params.lang or 'nil',

        key = 'getaward',
        type = "dreamcity_receive",
        bonus = send_rewards,
        
        total_score = op_total_score,
        cost = cost_money,
    }))

    return t_retCode.n_OK, ret_msg 
end

--请求分享码
M.national_secret_code = function ()
    local t_pre_check, t_pre_error = pre_national_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    local uin =  tonumber(ngx.ctx.m_params.uin)
    local t_national_conf = mis_data.t_currency.t_national_conf

    if (not uin) or (not t_national_conf) 
    or (not t_national_conf.task_cfg) 
    or (not t_national_conf.task_cfg.share_cfg) then 
		return t_retCode.n_PARAM_ERR, 'param error'
	end

    local ok, national_data = mis_data.get_user():get_national_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end 
    if (not national_data) 
    or (not national_data.task_data) 
    or (not national_data.task_data.total_score) then
        return t_retCode.n_WORK_ERR, '[ERROR] national_secret_code no national_data!'
    end

    --一天只能申请一个码
	if national_data.secret_data and os.date("%Y%m%d", national_data.secret_data.ctime) == os.date("%Y%m%d") then 
        return t_retCode.n_OK, { code = national_data.secret_data.code }
    end

    local b_ok, s_code = mis_tools.get_secret_code(mis_config.t_workType.s_NATIONAL, uin, t_national_conf.task_cfg.share_cfg)
    if b_ok~=t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] get_secret_code error", "uin="..uin, "s_code="..s_code)
        return b_ok, 'code error'
    end

    national_data.secret_data = {ctime = uu.now(), code = s_code}
    local ok2, s_desc = mis_data.get_user():set_national_data(national_data)
	if ok2 ~= t_retCode.n_OK then
		log.day_list(LOG_NAME, "[ERROR] set_sanrio_data save user code error", "uin="..uin
            , "s_desc="..uu.to_str(s_desc), "secret_data="..uu.to_str(national_data.secret_data))
		return ok2, s_desc
	end

    log.day_list(LOG_NAME, '[INFO_OK] national_secret_code', "apiid="..(ngx.ctx.m_params.apiid or 'nil')
        , 'uin='..uin, "ver="..(ngx.ctx.m_params.ver or 'nil'), "new_code="..uu.to_str(s_code))

	return t_retCode.n_OK, { code = s_code }
end

--使用分享码
M.national_code_exchange = function ()
    local t_pre_check, t_pre_error = pre_national_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    local exchange_uin =  tonumber(ngx.ctx.m_params.uin)
	local code 	= ngx.ctx.m_params.code
    local t_national_conf = mis_data.t_currency.t_national_conf

    if (not exchange_uin) or (not code) 
    or (not t_national_conf) 
    or (not t_national_conf.task_cfg) 
    or (not t_national_conf.task_cfg.share_cfg) then 
		return t_retCode.n_PARAM_ERR, 'param error'
	end

    local ok, exchange_user_data = mis_data.get_user(exchange_uin):get_national_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if (not exchange_user_data) 
    or (not exchange_user_data.task_data) 
    or (not exchange_user_data.task_data.total_score) 
    or (not exchange_user_data.task_data.task_list) then
        return t_retCode.n_WORK_ERR, '[ERROR] national_code_exchane no exchange_user_data!'
    end

    local ok2, t_ret, share_uin = mis_tools.exchange_secret_code(code, exchange_uin, exchange_user_data.task_data)
    if ok2~=t_retCode.n_OK then 
        log.day_list(LOG_NAME, "[ERROR] national_code_exchane", "uin="..exchange_uin
            , "code="..code, "t_ret="..uu.to_str(t_ret))
        return t_retCode.n_WORK_ERR 
    end

   	-- 分享者更新任务
	local ok3, share_user_data = mis_data.get_user(share_uin):get_national_data()
	if ok3~=t_retCode.n_OK then
		return t_retCode.n_SYS_ERR, 'ssdb error'
	end
	if (not share_user_data) 
    or (not share_user_data.task_data) 
    or (not share_user_data.task_data.total_score) 
    or (not share_user_data.task_data.task_list) then
        return t_retCode.n_WORK_ERR, '[ERROR] national_code_exchane no share_user_data!'
    end
    for _, v in pairs(share_user_data.task_data.task_list) do
        if v.event==29 and v.status==0 then 
            mis_tools.update_task(29, 1, share_user_data.task_data)
            break
        end
    end

    --set
    local n_code1, n_desc1 = mis_data.get_user(share_uin):set_national_data(share_user_data)
    if n_code1 ~= t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] national_code_exchane", "set_national_data error!", "share_uin="..share_uin)
        return n_code1, n_desc1
    end

    local n_code2, n_desc2 = mis_data.get_user(exchange_uin):set_national_data(exchange_user_data)
    if n_code2 ~= t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] national_code_exchane", "set_national_data error!", "exchange_uin="..exchange_uin)
        return n_code2, n_desc2
    end

    return t_retCode.n_OK, t_ret 
end

--排行榜
--参数： 
--返回值：
M.national_get_rank = function ()
    local t_pre_check, t_pre_error = pre_national_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    local uin =  tonumber(ngx.ctx.m_params.uin)
    if (not uin) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end

    local rank_data = {}
    rank_data.rank = get_share_rank()
    rank_data.op_user_data = get_user_rankinfo(uin)

    return t_retCode.n_OK, rank_data
end

M.national_set_rank = function ()
    local t_pre_check, t_pre_error = pre_national_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    local uin =  tonumber(ngx.ctx.m_params.uin)
    if (not uin) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end

    local test_data = {}
    local base_uin = 50000
    local base_score = 1
    for i=1, 95 do
        test_data[base_uin + i] = base_score + i
    end
    local map_id = mis_config.t_rank_server.s_mapid
    local t_name = mis_config.t_rank_server.s_name
    mis_bridge.set_cloud_national_score(map_id, t_name, test_data)
end

M.national_clear_rank = function ()
    local t_pre_check, t_pre_error = pre_national_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    mis_tools.clear_nginx_share(NATIONAL_SHARE.cache_name)

    local map_id = mis_config.t_rank_server.s_mapid
    local t_name = mis_config.t_rank_server.s_name
    mis_bridge.clear_cloud_national_rank(map_id, t_name)
end

--=========================== 2022国庆活动 end=============================

--=========================== 通用任务 start=============================
--前置检测
local function pre_currency_conf()
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local ver = ngx.ctx.m_params.ver
    local t_currency_conf = mis_data.t_currency.t_currency_conf

    local _check, _info = mis_tools.check_limit(t_currency_conf, apiid, ver)
    if not _check then 
        return t_retCode.n_AUTH_ERR, _info
    end

    return t_retCode.n_OK
end

M.currency_home_page = function ()
    local t_pre_check, t_pre_error = pre_currency_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end
    
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local t_currency_conf = mis_data.t_currency.t_currency_conf
    --log.debug("t_national_conf="..uu.to_str(t_currency_conf))

    if (not uin) or (not apiid) or (not t_currency_conf) 
    or (not t_currency_conf.task_cfg) 
    or (not t_currency_conf.important_cfg) 
    or (not t_currency_conf.important_cfg.act_no)
    or (not tonumber(t_currency_conf.important_cfg.act_no)) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end
    local act_no = tonumber(t_currency_conf.important_cfg.act_no)

    local ok, currency_data = mis_data.get_user():get_currency_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if not currency_data then 
        currency_data = {}
        currency_data[act_no] = {}
        currency_data[act_no].task_data = {}
    end
    if not currency_data[act_no] then 
        currency_data[act_no] = {}
        currency_data[act_no].task_data = {}
        --上上次的活动数据给清了，保留上次活动数据。
        currency_data[act_no - 2] = nil
    end

    --
    mis_tools.update_task_info_v2(uin, t_currency_conf.task_cfg, currency_data[act_no].task_data)

    local n_code, _desc = mis_data.get_user():set_currency_data(currency_data)
    if n_code ~= t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] currency_home_page", "set_currency_data error!", "uin="..uin)
        return n_code, _desc
    end

    return  t_retCode.n_OK, currency_data[act_no].task_data
end

M.currency_finsh_task = function ()
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local t_pre_check, t_pre_error = pre_currency_conf()
    if t_pre_check~=t_retCode.n_OK then 
        log.day_list(LOG_NAME, "[ERROR] currency_finsh_task", "pre_currency_conf error!", "uin="..uin)
        return t_pre_check, t_pre_error
    end

    local apiid = tonumber(ngx.ctx.m_params.apiid)
    
    local event = tonumber(ngx.ctx.m_params.event)
    local times = tonumber(ngx.ctx.m_params.times) 
    local special_key = tonumber(ngx.ctx.m_params.special_key)
    local t_currency_conf = mis_data.t_currency.t_currency_conf

    if (not apiid) or (not event) or (not times) or (not uin) 
    or (not t_currency_conf) 
    or (not t_currency_conf.task_cfg) 
    or (not t_currency_conf.important_cfg) 
    or (not t_currency_conf.important_cfg.act_no)
    or (not tonumber(t_currency_conf.important_cfg.act_no)) then 
        log.day_list(LOG_NAME, "[ERROR] currency_finsh_task", "param error!", "uin="..uin)
		return t_retCode.n_PARAM_ERR, 'param error'
	end
    local act_no = tonumber(t_currency_conf.important_cfg.act_no)


    local ok, currency_data = mis_data.get_user():get_currency_data()
    if ok~=t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] currency_finsh_task", "get_currency_data error!", "uin="..uin)
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if not currency_data then 
        currency_data = {}
        currency_data[act_no] = {}
        currency_data[act_no].task_data = {}
    end
    if not currency_data[act_no] then 
        currency_data[act_no] = {}
        currency_data[act_no].task_data = {}
        --上上次的活动数据给清了，保留上次活动数据。
        currency_data[act_no - 2] = nil
    end

    local ok2, rewards = mis_tools.update_task(event, times, currency_data[act_no].task_data, t_currency_conf.task_cfg, special_key)
    --[[
    if not ok2 then 
        log.day_list(LOG_NAME, "[ERROR] currency_finsh_task", "no finish task!", "uin="..uin, "event="..event
            , "times="..times, "special_key="..(special_key or "nil"))
        return t_retCode.n_WORK_ERR, 'update_task error--->no finish task!'
    end
    --]]

    local n_code, n_desc = mis_data.get_user():set_currency_data(currency_data)
    if n_code ~= t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] currency_finsh_task", "set_currency_data error!", "uin="..uin)
        return n_code, n_desc
    end

    --log.day_list(LOG_NAME, '[INFO] national_finsh_task', "apiid="..apiid, 'uin='..uin, "ver="..(ngx.ctx.m_params.ver or 'nil')
    --    , 'times='..times, 'event='..event, "special_key="..(special_key or "nil")
    --    , 'rewards='..uu.to_str(rewards), '[not add now!]now total_score='..(currency_data.task_data.total_score or "nil")
    --    , 'event_times_data='..(currency_data.task_data.events_finish_times[event] or "nil"))

    return t_retCode.n_OK, rewards
end

M.currency_get_task_rewards = function ()
    local t_pre_check, t_pre_error = pre_currency_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local task_id = tonumber(ngx.ctx.m_params.task_id)
    local t_currency_conf = mis_data.t_currency.t_currency_conf

    if (not uin) or (not apiid) or (not task_id) 
    or (not t_currency_conf.important_cfg) 
    or (not t_currency_conf.important_cfg.act_no)
    or (not tonumber(t_currency_conf.important_cfg.act_no)) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end
    local act_no = tonumber(t_currency_conf.important_cfg.act_no)

    local ok, currency_data = mis_data.get_user():get_currency_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if (not currency_data)
    or (not currency_data[act_no])
    or (not currency_data[act_no].task_data) 
    or (not currency_data[act_no].task_data.total_score)
    or (not currency_data[act_no].task_data.task_list) 
    or (not currency_data[act_no].task_data.task_list[task_id]) 
    or (not currency_data[act_no].task_data.task_list[task_id].bonus)
    or (not currency_data[act_no].task_data.task_list[task_id].bonus.num) 
    or (not tonumber(currency_data[act_no].task_data.task_list[task_id].bonus.num)) then 
        return t_retCode.n_WORK_ERR, '[ERROR] currency_get_task_rewards no currency_data!'
    end

    if currency_data[act_no].task_data.task_list[task_id].status ~= mis_tools.REWARDS_STATUS.READY then 
        return t_retCode.n_WORK_ERR, '[ERROR] currency_get_task_rewards not ready!'
    end

    local task_data = currency_data[act_no].task_data
    task_data.task_list[task_id].status = mis_tools.REWARDS_STATUS.ALREADY
    local get_score = tonumber(currency_data[act_no].task_data.task_list[task_id].bonus.num)
    currency_data[act_no].task_data.total_score = currency_data[act_no].task_data.total_score + get_score  

    local n_code, _desc = mis_data.get_user():set_currency_data(currency_data)
    if n_code ~= t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] currency_get_task_rewards", "set_currency_data error!", "uin="..uin)
        return n_code, _desc
    end

    --埋点数据
    mis_log.remote_pure_day("currency_receive", mis_common.table_to_json({
        ip = ngx.ctx.m_params.s_remoteAddr or ngx.ctx.xff or ngx.var.remote_addr or "nil",
        uin = uin,
        time = ngx.ctx.m_params.createTime or uu.now(),
        country = ngx.ctx.m_params.country or 'nil',
        apiid = ngx.ctx.m_params.apiid or 'nil',
        ver = ngx.ctx.m_params.ver or 'nil',
        lang = ngx.ctx.m_params.lang or 'nil',

        key = 'getaward',
        type = "currency_receive",
        num = get_score,
        id = currency_data[act_no].task_data.task_list[task_id].bonus.itemId,
        report_id = currency_data[act_no].task_data.task_list[task_id].report_id
    }))

    --[[
    log.day_list(LOG_NAME, '[INFO] currency_get_task_rewards ok', 'uin='..uin, "apiids="..apiid, "task_id="..task_id
        , "add_score="..tonumber(currency_data[act_no].task_data.task_list[task_id].bonus.num)
        , "task_data.score="..currency_data[act_no].task_data.total_score
        , "now_time="..uu.now()
    )
    --]]

    return  t_retCode.n_OK, task_data.task_list[task_id].bonus
end


--兑换商店
--参数： 无
--返回值： status 0正常可兑换 1已拥有 2兑换次数不足 
M.currency_exchange_shop = function ()
    local t_pre_check, t_pre_error = pre_currency_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local t_currency_conf = mis_data.t_currency.t_currency_conf

    if (not uin) or (not apiid) or (not t_currency_conf)  
    or (not t_currency_conf.shop_cfg)
    or (not t_currency_conf.important_cfg) 
    or (not t_currency_conf.important_cfg.act_no)
    or (not tonumber(t_currency_conf.important_cfg.act_no)) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end
    local act_no = tonumber(t_currency_conf.important_cfg.act_no)

    local ok, currency_data = mis_data.get_user():get_currency_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if (not currency_data) 
    or (not currency_data[act_no])
    or (not currency_data[act_no].task_data) 
    or (not currency_data[act_no].task_data.total_score) then  
        return t_retCode.n_WORK_ERR, '[ERROR] currency_exchange_shop no currency_data!'
    end

    local new_data_flag = false
    if (not currency_data[act_no].shop_data) then
        currency_data[act_no].shop_data = {}
        new_data_flag = true
    end

    local shop_info, update_flag = mis_tools.exchange_shop(t_currency_conf.shop_cfg, currency_data[act_no].shop_data)
 
    if new_data_flag or update_flag then 
        local n_code, _desc = mis_data.get_user():set_currency_data(currency_data)
        if n_code ~= t_retCode.n_OK then
            log.day_list(LOG_NAME, "[ERROR] currency_exchange_shop", "set_national_data error!", "uin="..uin)
            return n_code, _desc
        end
    end

    local ret_msg = {}
    ret_msg.shop_info = shop_info
    ret_msg.total_score = currency_data[act_no].task_data.total_score

    return  t_retCode.n_OK, ret_msg
end

--兑换商店兑换物品
--参数：item_id 商店配置索引ID
--返回值： 兑换到的物品+当前总分
M.currency_exchange_items = function ()
    local t_pre_check, t_pre_error = pre_currency_conf()
    if t_pre_check~=t_retCode.n_OK then 
        return t_pre_check, t_pre_error
    end

    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local item_id = tonumber(ngx.ctx.m_params.item_id)
    local t_propId = tonumber(ngx.ctx.m_params.propId)
    local t_currency_conf = mis_data.t_currency.t_currency_conf

    if (not uin) or (not apiid) or (not item_id) 
    or (not t_propId)
    or (not t_currency_conf)
    or (not t_currency_conf.important_cfg) 
    or (not t_currency_conf.important_cfg.act_no)
    or (not tonumber(t_currency_conf.important_cfg.act_no))
    or (not t_currency_conf.shop_cfg)
    or (not t_currency_conf.shop_cfg[item_id]) 
    or (not t_currency_conf.shop_cfg[item_id].propId)
    or (not t_currency_conf.shop_cfg[item_id].propNum)
    or (not t_currency_conf.shop_cfg[item_id].cost) 
    or (not t_currency_conf.shop_cfg[item_id].exCount) 
    or (not tonumber(t_currency_conf.shop_cfg[item_id].propId)) 
    or (not tonumber(t_currency_conf.shop_cfg[item_id].propNum))
    or (not tonumber(t_currency_conf.shop_cfg[item_id].cost))
    or (not tonumber(t_currency_conf.shop_cfg[item_id].exCount)) 
    or (not t_currency_conf.task_cfg) 
    or (not t_currency_conf.task_cfg.task_list)
    or (not t_currency_conf.task_cfg.task_list[1])
    or (not t_currency_conf.task_cfg.task_list[1].bonus)
    or (not t_currency_conf.task_cfg.task_list[1].bonus.itemId) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end
    local act_no = tonumber(t_currency_conf.important_cfg.act_no)

    local ok, currency_data = mis_data.get_user():get_currency_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end 
    if (not currency_data) 
    or (not currency_data[act_no])
    or (not currency_data[act_no].shop_data) 
    or (not currency_data[act_no].task_data)
    or (not currency_data[act_no].task_data.total_score) then
        return t_retCode.n_WORK_ERR, '[ERROR] currency_exchange_items no currency_data!'
    end

    --兑换次数是否充足
    local propId = tonumber(t_currency_conf.shop_cfg[item_id].propId)
    if not propId 
    or (propId~=t_propId) then 
        return t_retCode.n_PARAM_ERR, 'param error'   
    end
    if (currency_data[act_no].shop_data[propId]) 
    and (tonumber(currency_data[act_no].shop_data[propId]))
    and (tonumber(currency_data[act_no].shop_data[propId]) >= tonumber(t_currency_conf.shop_cfg[item_id].exCount) ) then 
        return t_retCode.n_WORK_ERR, '[ERROR] currency_exchange_items exCount not enough!'
    end

    --代币是否充足
    local cost_money = (tonumber(t_currency_conf.shop_cfg[item_id].cost))
    if (currency_data[act_no].task_data.total_score) < cost_money then
        return t_retCode.n_WORK_ERR, '[ERROR] currency_exchange_items money not enough!' 
    end 

    local reward = t_currency_conf.shop_cfg[item_id]
    --发给账号服需要这种结构
    local send_rewards = {}
    local one_reward = {}
    one_reward.id  = tonumber(reward.propId)
    one_reward.num  = tonumber(reward.propNum)
    table.insert(send_rewards, one_reward)

    --扣代币
    local op_total_score = currency_data[act_no].task_data.total_score
    currency_data[act_no].task_data.total_score = currency_data[act_no].task_data.total_score - cost_money
    --次数累计
    if not currency_data[act_no].shop_data[propId] then
        currency_data[act_no].shop_data[propId] = 1
    else
        currency_data[act_no].shop_data[propId] = currency_data[act_no].shop_data[propId] + 1
    end

    --set
    local n_code, _desc = mis_data.get_user():set_currency_data(currency_data)
    if n_code ~= t_retCode.n_OK then
        log.day_list(LOG_NAME, "[ERROR] currency_exchange_items", "set_national_data error!", "uin="..uin)
        return n_code, _desc
    end

    --账号服发奖
    if #send_rewards>0 then
        --账号服发奖
        local ok2, reason_1, s_items, s_reason = mis_bridge.add_items(uin, send_rewards, "mis_currency", mis_config.t_workType.s_CURRENCY)
        if ok2~=t_retCode.n_OK then 
            log.day_list(LOG_NAME, '[ERROR] currency_exchange_items call accout error!', "uin="..uin, "apiid="..apiid, "send_rewards="..uu.to_str(send_rewards)
                ,"accout_ret="..uu.to_str(ok2), "reason_1="..reason_1, "s_items="..uu.to_str(s_items), "s_reason="..s_reason)
            return t_retCode.n_SYS_ERR, "call account add_items error!"
        end

        --埋点数据
        mis_log.remote_pure_day("currency_exchange", mis_common.table_to_json({
            ip = ngx.ctx.m_params.s_remoteAddr or ngx.ctx.xff or ngx.var.remote_addr or "nil",
            uin = uin,
            time = ngx.ctx.m_params.createTime or uu.now(),
            country = ngx.ctx.m_params.country or 'nil',
            apiid = ngx.ctx.m_params.apiid or 'nil',
            ver = ngx.ctx.m_params.ver or 'nil',
            lang = ngx.ctx.m_params.lang or 'nil',

            key = 'getaward',
            type = "currency_exchange",
            bonus = send_rewards,
            
            item_id = reward.id,
            cost_id =  t_currency_conf.task_cfg.task_list[1].bonus.itemId,
            cost_num = cost_money,
            total_score = op_total_score,
        }))
    end
    
    local ret_msg = {}
    ret_msg.total_score = currency_data[act_no].task_data.total_score
    ret_msg.send_rewards = send_rewards

    return t_retCode.n_OK, ret_msg 
end

M.currency_reset_data = function (id)
    local t_currency_conf = mis_data.t_currency.t_currency_conf
    if (not t_currency_conf)  
    or (not t_currency_conf.important_cfg) 
    or (not t_currency_conf.important_cfg.act_no)
    or (not tonumber(t_currency_conf.important_cfg.act_no)) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end
    local act_no = tonumber(t_currency_conf.important_cfg.act_no)

    local ok, currency_data = mis_data.get_user():get_currency_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    currency_data[act_no] = nil

    local ok2, code = mis_data.get_user():set_currency_data(currency_data)

    return t_retCode.n_OK
end

M.currency_add_score = function ()
    local score =  tonumber(ngx.ctx.m_params.score)
    local t_currency_conf = mis_data.t_currency.t_currency_conf

    if (not t_currency_conf)  
    or (not t_currency_conf.important_cfg) 
    or (not t_currency_conf.important_cfg.act_no)
    or (not tonumber(t_currency_conf.important_cfg.act_no)) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end
    local act_no = tonumber(t_currency_conf.important_cfg.act_no)

    local ok, currency_data = mis_data.get_user():get_currency_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end

    if not currency_data 
    or (not currency_data[act_no].task_data)
    or (not currency_data[act_no].task_data.total_score) then 
        return t_retCode.n_SYS_ERR, 'param error'
    end

    currency_data[act_no].task_data.total_score = currency_data[act_no].task_data.total_score + score

    mis_data.get_user():set_currency_data(currency_data)

    return t_retCode.n_OK
end


--=========================== 通用任务 end=============================

return M
